package ua.senfiron.vk.photo.viewer.vkprovider;

import java.util.ArrayList;
import java.util.Calendar;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import ua.senfiron.vk.photo.viewer.util.HttpUtilities;
import ua.senfiron.vk.photo.viewer.util.StringUtilities;
import android.content.Context;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.AsyncTask;

/**
 * 
 * Singleton class that stores information about a current vk.com session
 *
 */
public class VkProvider {
    
    private static volatile VkProvider instance;
    
    private VkProvider() {}
 
    public static VkProvider getInstance() {
        if (instance == null) {
            synchronized (VkProvider.class) {
                if (instance == null) {
                    instance = new VkProvider();
                }
            }
        }
        return instance;
    }
    
    public static final String VK_PROVIDER_PREFERENCES = "VkProviderPreferences";
    private static final String CLIENT_ID = "3802648";
    private String mAccessToken;
    private String mUserId;
    private long mExpireTime = 0;
    private ArrayList<VkAlbum> mAlbums = new ArrayList<VkAlbum>();
    private int mCurrentAlbumIndex = -1;
    private int mCurrentPhotoIndex = -1;
    
    public String getAccessToken() {
        return mAccessToken;
    }

    public String getUserId() {
        return mUserId;
    }

    public long getExpireTime() {
        return mExpireTime;
    }
    
    public ArrayList<VkAlbum> getAlbums()
    {
        return mAlbums;
    }
    
    public VkAlbum getCurrentAlbum() {
        if(mCurrentAlbumIndex == -1)
            return null;
        return mAlbums.get(mCurrentAlbumIndex);
    }

    public void setCurrentAlbumIndex(int currentAlbumIndex) {
        if(mCurrentAlbumIndex != currentAlbumIndex){
            this.mCurrentAlbumIndex = currentAlbumIndex;
            this.mCurrentPhotoIndex = -1;
        }
    }
    public VkPhoto getCurrentPhoto() {
        if(mCurrentPhotoIndex == -1 || getCurrentAlbum() == null)
            return null;
        return getCurrentAlbum().getPhotos().get(mCurrentPhotoIndex);
    }
    public int getCurrentPhotoIndex() {
        return mCurrentPhotoIndex;
    } 
    public void setCurrentPhotoIndex(int currentPhotoIndex) {
        this.mCurrentPhotoIndex = currentPhotoIndex;
    }
    
    public String getLoginURL()
    {
        Uri.Builder builder = Uri.parse(
                "https://oauth.vk.com/authorize")
                .buildUpon();
        builder.appendQueryParameter("client_id", CLIENT_ID);
        builder.appendQueryParameter("redirect_uri", "https://oauth.vk.com/blank.html");
        builder.appendQueryParameter("display", "mobile");
        builder.appendQueryParameter("scope", "4");//photo
        builder.appendQueryParameter("response_type", "token");
        
        return builder.build().toString();
    }
    
    /**
     * Try to extract access_token, user_id, expires_in from URL
     * 
     * @param url to extract token from
     * @return true if access_token was successfully extracted, otherwise false
     */
    public Boolean extractTokenFromUrl(String url)
    {
        if(!url.contains("access_token"))return false;

        mAccessToken = StringUtilities.stringBetween(url, "access_token=", "&");
        mUserId = StringUtilities.stringBetween(url, "user_id=", "&");
        String expiresIn = StringUtilities.stringBetween(url, "expires_in=", "&");
           
        Calendar rightNow = Calendar.getInstance();
        rightNow.add(Calendar.SECOND, Integer.valueOf(expiresIn));
        mExpireTime = rightNow.getTimeInMillis();
        
        return true;
    }
    
    public void logOut(Context context){

        this.clearData();
        this.clearSharedPreferences(context);
        HttpUtilities.clearCookies(context);
    }
    public Boolean saveToSharedPreferences(Context context)
    {
        SharedPreferences settings = context.getSharedPreferences(VK_PROVIDER_PREFERENCES, 0);
        SharedPreferences.Editor editor = settings.edit();
        editor.putString("access_token", mAccessToken);
        editor.putString("user_id", mUserId);
        editor.putLong("expire_time", mExpireTime);
        
        editor.commit();
        return true;
    }
    
    /**
     * Try to load access_token, user_id, expires_in from shared preferences
     * 
     * @param context
     * @return true if access_token isn't expire and data loaded, otherwise false
     */
    public Boolean loadFromSharedPreferences(Context context)
    {
        SharedPreferences settings = context.getSharedPreferences(VK_PROVIDER_PREFERENCES, 0);
        mAccessToken = settings.getString("access_token", null);
        mUserId = settings.getString("user_id", null);
        mExpireTime = settings.getLong("expire_time", 0);

        if(mExpireTime != 0)
        {
            Calendar rightNow = Calendar.getInstance();
            Calendar expirationDate = Calendar.getInstance();
            expirationDate.setTimeInMillis(mExpireTime);
    
            if(rightNow.compareTo(expirationDate) < 0)
                if(mAccessToken != null && mUserId != null)
                    return true;
        }
        return false;
    }
    public boolean clearSharedPreferences(Context context)
    {
        context.getSharedPreferences(VK_PROVIDER_PREFERENCES, 0).edit().clear().commit();
        return true;
    }
    
    public void clearData(){
        
        mAccessToken = null;
        mUserId = null;
        mExpireTime = 0;
        mAlbums.clear();
        mCurrentAlbumIndex = -1;
        mCurrentPhotoIndex = -1;
        
    }
    
    /*
     * Albums methods
     */
    
    public static interface OnAlbumsLoadedListener
    {
        public void onAlbumsLoaded(ArrayList<VkAlbum> albums);
    }

    public void loadAlbumsAsync(final OnAlbumsLoadedListener callback)
    {
        AsyncTask<String, Void, ArrayList<VkAlbum>> task = new AsyncTask<String, Void, ArrayList<VkAlbum>>(){

            @Override
            protected ArrayList<VkAlbum> doInBackground(String... params) {
                return loadAlbums();
            }
            
            @Override
            protected void onPostExecute(ArrayList<VkAlbum> albums) {
                callback.onAlbumsLoaded(albums);
            }};
            task.execute();
            
    }
    
    public ArrayList<VkAlbum> loadAlbums()
    {
        Uri.Builder builder = Uri.parse(
                "https://api.vk.com/method/photos.getAlbums")
                .buildUpon();
        builder.appendQueryParameter("access_token", mAccessToken);
        builder.appendQueryParameter("uid", mUserId);
        builder.appendQueryParameter("need_covers", "1");
        builder.appendQueryParameter("photo_sizes", "1");
        
        String response = HttpUtilities.getData(builder.build().toString());

        mAlbums.clear();
        
        try {

            JSONObject jsonResponse = new JSONObject(response);                        
            JSONArray array = jsonResponse.getJSONArray("response");
                        
            for (int i = 0; i < array.length(); i++) {
                
                JSONObject json = array.getJSONObject(i);
                
                int albumId = json.getInt("aid");
                String title = json.getString("title");
                int thumbId = json.getInt("thumb_id");
                
                VkPhoto thumb = new VkPhoto(thumbId, albumId, "");
                
                if(json.has("sizes"))
                {
                    JSONArray sizes = json.getJSONArray("sizes");
                    loadSizesInfo(thumb, sizes);
                }    
                
                VkAlbum album = new VkAlbum(albumId, title, thumb);
                mAlbums.add(album);
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        return mAlbums;  
    }
    
    /*
     * Photos methods
     */
    
    public static interface OnPhotosLoadedListener
    {
        public void onPhotosLoaded(ArrayList<VkPhoto> photos);
    }

    public void loadPhotosAsync(final OnPhotosLoadedListener callback)
    {
        AsyncTask<String, Void, ArrayList<VkPhoto>> task = new AsyncTask<String, Void, ArrayList<VkPhoto>>(){

            @Override
            protected ArrayList<VkPhoto> doInBackground(String... params) {
                return loadPhotos();
            }
            
            @Override
            protected void onPostExecute(ArrayList<VkPhoto> photos) {
                callback.onPhotosLoaded(photos);
            }};
            task.execute();
            
    }
    public ArrayList<VkPhoto> loadPhotos()
    {
        return loadPhotos(mCurrentAlbumIndex);
    }
    public ArrayList<VkPhoto> loadPhotos(int albumIndex)
    {
        VkAlbum currentAlbum = mAlbums.get(albumIndex);
        if(currentAlbum == null)
             return null;
        
        Uri.Builder builder = Uri.parse(
                "https://api.vk.com/method/photos.get")
                .buildUpon();
        builder.appendQueryParameter("access_token", mAccessToken);
        builder.appendQueryParameter("uid", mUserId);
        builder.appendQueryParameter("aid", String.valueOf(currentAlbum.getAlbumID()));
        builder.appendQueryParameter("photo_sizes", "1");
        
        String response = HttpUtilities.getData(builder.build().toString());
             
        ArrayList<VkPhoto> photos = currentAlbum.getPhotos();
        photos.clear();
        
        try {

            JSONObject jsonResponse = new JSONObject(response);                        
            JSONArray array = jsonResponse.getJSONArray("response");
                        
            for (int i = 0; i < array.length(); i++) {
                
                JSONObject json = array.getJSONObject(i);
                
                int photoId = json.getInt("pid");
                int albumId = json.getInt("aid");
                String text = json.getString("text");
                
                VkPhoto photo = new VkPhoto(photoId, albumId, text);
                if(json.has("sizes"))
                {
                    JSONArray sizes = json.getJSONArray("sizes");
                    loadSizesInfo(photo, sizes);
                }                
                photos.add(photo);
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return photos;
    }
    
    private void loadSizesInfo(VkPhoto photo, JSONArray sizes) throws JSONException
    {
        ArrayList<VkPhoto.VkPhotoInfo> sizesInfo = new ArrayList<VkPhoto.VkPhotoInfo>();
        
        for(int i = 0; i < sizes.length(); i++) {
            
            JSONObject json = sizes.getJSONObject(i);
            
            int width = json.getInt("width");
            int height = json.getInt("height");
            String type = json.getString("type");
            String src = json.getString("src");
                                  
            VkPhoto.VkPhotoInfo info = new VkPhoto.VkPhotoInfo(src,width,height,type);
            sizesInfo.add(info);
        }
        photo.setSizesInfo(sizesInfo);
    }

}
